#-*- coding:utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
#    d$
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

import time
from datetime import date
from datetime import datetime
from datetime import timedelta
from dateutil import relativedelta

from openerp import api, tools
from openerp.osv import fields, osv
from openerp.tools.translate import _
import openerp.addons.decimal_precision as dp

from openerp.tools.safe_eval import safe_eval as eval

class hr_payslip(osv.osv):
    '''
    Pay Slip
    '''
    _inherit = 'hr.payslip'
    _description = 'Inherit Pay Slip'
    
    def compute_sheet(self, cr, uid, ids, context=None):
        slip_line_pool = self.pool.get('hr.payslip.line')
        hr_salary_rule = self.pool.get('hr.salary.rule')
        sequence_obj = self.pool.get('ir.sequence')
        hr_pkp_obj = self.pool.get('hr.pkp')
        for payslip in self.browse(cr, uid, ids, context=context):
            number = payslip.number or sequence_obj.get(cr, uid, 'salary.slip')
            #delete old payslip lines
            old_slipline_ids = slip_line_pool.search(cr, uid, [('slip_id', '=', payslip.id)], context=context)
#            old_slipline_ids
            if old_slipline_ids:
                slip_line_pool.unlink(cr, uid, old_slipline_ids, context=context)
            if payslip.contract_id:
                #set the list of contract for which the rules have to be applied
                contract_ids = [payslip.contract_id.id]
            else:
                #if we don't give the contract, then the rules to apply should be for all current contracts of the employee
                contract_ids = self.get_contract(cr, uid, payslip.employee_id, payslip.date_from, payslip.date_to, context=context)
            lines = [(0,0,line) for line in self.pool.get('hr.payslip').get_payslip_lines(cr, uid, contract_ids, payslip.id, context=context)]
            self.write(cr, uid, [payslip.id], {'line_ids': lines, 'number': number,}, context=context)
            
            
            hr_ps_line_ids = slip_line_pool.search(cr, uid, [('slip_id','=',payslip.id)])
            total_gaji_sebulan = total_pkp_setahun = tax = pph_terhutang_1_th = pph_terhutang_1_bln = gaji_bersih = 0
            
            for hr_ps_line in slip_line_pool.browse(cr, uid, hr_ps_line_ids, context=context):
                if hr_ps_line.name and hr_ps_line.name  == 'Total':
                    total_gaji_sebulan = hr_ps_line.total
                if hr_ps_line.name and hr_ps_line.name  == 'Penghasilan_Kena_Pajak':
                    total_pkp_setahun =  hr_ps_line.total
            
            pkp_ids = hr_pkp_obj.search(cr, uid, [('min_nominal','<=',total_pkp_setahun),('max_nominal','>=',total_pkp_setahun)])
            for pkp in hr_pkp_obj.browse(cr, uid, pkp_ids, context=context):
                tax = pkp.tax/100
            pph_terhutang_1_th = total_pkp_setahun * tax
            pph_terhutang_1_bln = pph_terhutang_1_th / 12
            gaji_bersih = total_gaji_sebulan - pph_terhutang_1_bln   
            
            for hr_ps_line_update in slip_line_pool.browse(cr, uid, hr_ps_line_ids, context=context):
                if hr_ps_line_update.name and hr_ps_line_update.name  == 'PPh':
                    print "masuk"
                    print hr_ps_line_update.id
                    slip_line_pool.write(cr, uid, [hr_ps_line_update.id], {'amount_fix': pph_terhutang_1_bln,'amount': pph_terhutang_1_bln,'total': pph_terhutang_1_bln,})
                    print "lewat"
                if hr_ps_line_update.name and hr_ps_line_update.name  == 'Gaji_bersih':
                    slip_line_pool.write(cr, uid, [hr_ps_line_update.id], {'amount_fix': gaji_bersih,'amount': gaji_bersih,'total': gaji_bersih,})
            
            print "gaji sebulan belum pajak"+str(total_gaji_sebulan)
            print "gaji setahun "+str(total_pkp_setahun)
            print "pajak"+str(tax)
            print "pph 1 th"+str(pph_terhutang_1_th)
            print "pph 1 bln"+str(pph_terhutang_1_bln)
            print "gaji bersih = "+str(gaji_bersih)
#             pph_array = {
#                  'name': hr_ps_line.name,
#                  'code':hr_ps_line.code,
#                  'category_id': hr_ps_line.category_id.id,
#                  'quantity': hr_ps_line.quantity,
#                  'rate': hr_ps_line.rate,
#                  'amount': hr_ps_line.amount,
#                  'total': hr_ps_line.total,
#             }    
      

            
        return True
    
    def get_worked_day_lines(self, cr, uid, contract_ids, date_from, date_to, context=None):
        """
        @param contract_ids: list of contract id
        @return: returns a list of dict containing the input that should be applied for the given contract between date_from and date_to
        """
        def was_on_leave(employee_id, datetime_day, context=None):
            res = False
            day = datetime_day.strftime("%Y-%m-%d")
            holiday_ids = self.pool.get('hr.holidays').search(cr, uid, [('state','=','validate'),('employee_id','=',employee_id),('type','=','remove'),('date_from','<=',day),('date_to','>=',day)])
            if holiday_ids:
                res = self.pool.get('hr.holidays').browse(cr, uid, holiday_ids, context=context)[0].holiday_status_id.name
            return res
        
        def check_presence(employee_id, datetime_from_day,datetime_to_day, context=None):
            res1 = {}
            total_hours = total_days = 0

            presence_ids = self.pool.get('hr.attendance').search(cr, uid, [('employee_id','=',employee_id),('worked_hours','>','0'),('name','>=',datetime_from_day),('name','<=',datetime_to_day)])

            for details in self.pool.get('hr.attendance').browse(cr, uid, presence_ids, context=context) :
                 total_days +=  1
                 total_hours += details.worked_hours
            
            res1['total_hours'] = total_hours
            res1['total_days'] = total_days     
            return res1
        
        def check_ot(employee_id, datetime_from_day,datetime_to_day, context=None):
            res2 = {}
            total_ot_hours = 0

            overtime_ids = self.pool.get('hr.overtime').search(cr, uid, [('employee_id','=',employee_id),('date_from','>=',datetime_from_day),('date_to','<=',datetime_to_day)])

            for ot in self.pool.get('hr.overtime').browse(cr, uid, overtime_ids, context=context) :
                 total_ot_hours += ot.actual_ot_hours
            
            res2['total_ot_hours'] = total_ot_hours   
            return res2
        
        res = []
        for contract in self.pool.get('hr.contract').browse(cr, uid, contract_ids, context=context):
            if not contract.working_hours:
                #fill only if the contract as a working schedule linked
                continue
            attendances = {
                 'name': _("Normal Working Days paid at 100%"),
                 'sequence': 1,
                 'code': 'WORK100',
                 'number_of_days': 0.0,
                 'number_of_hours': 0.0,
                 'contract_id': contract.id,
            }
            leaves = {}
            day_from = datetime.strptime(date_from,"%Y-%m-%d")
            day_to = datetime.strptime(date_to,"%Y-%m-%d")
            nb_of_days = (day_to - day_from).days + 1
            for day in range(0, nb_of_days):
                working_hours_on_day = self.pool.get('resource.calendar').working_hours_on_day(cr, uid, contract.working_hours, day_from + timedelta(days=day), context)
                if working_hours_on_day:
                    #the employee had to work
                    leave_type = was_on_leave(contract.employee_id.id, day_from + timedelta(days=day), context=context)
                    if leave_type:
                        #if he was on leave, fill the leaves dict
                        if leave_type in leaves:
                            leaves[leave_type]['number_of_days'] += 1.0
                            leaves[leave_type]['number_of_hours'] += working_hours_on_day
                        else:
                            leaves[leave_type] = {
                                'name': leave_type,
                                'sequence': 20,
                                'code': leave_type,
                                'number_of_days': 1.0,
                                'number_of_hours': working_hours_on_day,
                                'contract_id': contract.id,
                            }
                    else:
                        #add the input vals to tmp (increment if existing)
                        attendances['number_of_days'] += 1.0
                        attendances['number_of_hours'] += working_hours_on_day

            presence_array = {}
            presence = check_presence(contract.employee_id.id, str(day_from), str(day_to), context=context)
            if presence:
                presence_array = {
                     'name': _("Presences"),
                     'sequence': 2,
                     'code': 'PRESENCES',
                     'number_of_days': presence['total_days'],
                     'number_of_hours': presence['total_hours'],
                     'contract_id': contract.id,
                }
            else :
                presence_array = {
                     'name': _("Presences"),
                     'sequence': 2,
                     'code': 'PRESENCES',
                     'number_of_days': 0.0,
                     'number_of_hours':0.0,
                     'contract_id': contract.id,  
                }     
            
            overtime_array = {}
            overtime = check_ot(contract.employee_id.id, str(day_from), str(day_to), context=context)
            if overtime:
                overtime_array = {
                     'name': _("Overtime"),
                     'sequence': 3,
                     'code': 'OVERTIME',
                     'number_of_days': 0,
                     'number_of_hours': overtime['total_ot_hours'],
                     'contract_id': contract.id,
                }
            else :
                  overtime_array = {
                     'name': _("Overtime"),
                     'sequence': 3,
                     'code': 'OVERTIME',
                     'number_of_days': 0.0,
                     'number_of_hours':0.0,
                     'contract_id': contract.id,  
                 }    
                           
            transport_array ={}
            transport_array = {
                     'name': _("Transport"),
                     'sequence': 4,
                     'code': 'TRANSPORT',
                     'number_of_days': presence['total_days'],
                     'number_of_hours':0.0,
                     'contract_id': contract.id,  
                 } 
            incentive_array ={}
            incentive_array = {
                     'name': _("Incentive"),
                     'sequence': 6,
                     'code': 'INCENTIVE',
                     'number_of_days': presence['total_days'],
                     'number_of_hours':0.0,
                     'contract_id': contract.id,  
                 } 
            meal_allowance_array ={}
            meal_allowance_array = {
                     'name': _("Meal Allowance"),
                     'sequence': 7,
                     'code': 'MEAL_ALLOWANCE',
                     'number_of_days': presence['total_days'],
                     'number_of_hours':0.0,
                     'contract_id': contract.id,  
                 } 
                    
            leaves = [value for key,value in leaves.items()]
            res += [attendances] + [presence_array] + [overtime_array] + [transport_array] + [incentive_array] +  [meal_allowance_array] + leaves    
        return res
    
    def get_line_idss(self, cr, uid,ids, contract_ids, context=None):
        """
        @param contract_ids: list of contract id
        @return: returns a list of dict containing the input that should be applied for the given contract between date_from and date_to
        """
        rule_obj = self.pool.get('hr.salary.rule')
        payroll_structure_obj = self.pool.get('hr.payroll.structure')
        hr_payslip_line_obj = self.pool.get('hr.payslip.line')
        hr_payslip_obj = self.pool.get('hr.payslip')
        res = []
        for contract in self.pool.get('hr.contract').browse(cr, uid, contract_ids, context=context):
            if not contract.working_hours:
                #fill only if the contract as a working schedule linked
                continue
 
            structure_ids = contract.struct_id.rule_ids
            print "cccccc"
            print structure_ids
            print "ccccc"
            pph_array = {}
            for structure_rule in structure_ids:
                if structure_rule.code == 'pph_21' :
                    print 9999999
                    print ids
                    print 9999999
                    ps_id = False
                    for payslip in hr_payslip_obj.browse(cr, uid, ids, context=context):
                        print payslip.id
                        print payslip.name
                        print 1111111
                        ps_id = payslip.id
#                     ,('slip_id','=',slip_id.id)
                    hr_ps_line_ids = hr_payslip_line_obj.search(cr, uid, [('salary_rule_id','=',structure_rule.id),('slip_id','=',ps_id)])
                    for hr_ps_line in hr_payslip_line_obj.browse(cr, uid, hr_ps_line_ids, context=context):
                        pph_array = {
                             'name': structure_rule.name,
                             'code':structure_rule.code,
                             'category_id': structure_rule.category_id.id,
                             'quantity': 0,
                             'rate': 0,
                             'amount': 0,
                             'total': hr_ps_line.total + 1,
                        }    
                 
            res += [pph_array]    
        return res
        
    def onchange_employee_id(self, cr, uid, ids, date_from, date_to, employee_id=False, contract_id=False, context=None):
        empolyee_obj = self.pool.get('hr.employee')
        contract_obj = self.pool.get('hr.contract')
        worked_days_obj = self.pool.get('hr.payslip.worked_days')
        input_obj = self.pool.get('hr.payslip.input')

        if context is None:
            context = {}
        #delete old worked days lines
        old_worked_days_ids = ids and worked_days_obj.search(cr, uid, [('payslip_id', '=', ids[0])], context=context) or False
        if old_worked_days_ids:
            worked_days_obj.unlink(cr, uid, old_worked_days_ids, context=context)

        #delete old input lines
        old_input_ids = ids and input_obj.search(cr, uid, [('payslip_id', '=', ids[0])], context=context) or False
        if old_input_ids:
            input_obj.unlink(cr, uid, old_input_ids, context=context)


        #defaults
        res = {'value':{
                      'line_ids':[],
                      'input_line_ids': [],
                      'worked_days_line_ids': [],
                      #'details_by_salary_head':[], TODO put me back
                      'name':'',
                      'contract_id': False,
                      'struct_id': False,
                      }
            }
        if (not employee_id) or (not date_from) or (not date_to):
            return res
        ttyme = datetime.fromtimestamp(time.mktime(time.strptime(date_from, "%Y-%m-%d")))
        employee_id = empolyee_obj.browse(cr, uid, employee_id, context=context)
        res['value'].update({
                    'name': _('Salary Slip of %s for %s') % (employee_id.name, tools.ustr(ttyme.strftime('%B-%Y'))),
                    'company_id': employee_id.company_id.id
        })

        if not context.get('contract', False):
            #fill with the first contract of the employee
            contract_ids = self.get_contract(cr, uid, employee_id, date_from, date_to, context=context)
        else:
            if contract_id:
                #set the list of contract for which the input have to be filled
                contract_ids = [contract_id]
            else:
                #if we don't give the contract, then the input to fill should be for all current contracts of the employee
                contract_ids = self.get_contract(cr, uid, employee_id, date_from, date_to, context=context)

        if not contract_ids:
            return res
        contract_record = contract_obj.browse(cr, uid, contract_ids[0], context=context)
        res['value'].update({
                    'contract_id': contract_record and contract_record.id or False
        })
        struct_record = contract_record and contract_record.struct_id or False
        if not struct_record:
            return res
        res['value'].update({
                    'struct_id': struct_record.id,
        })
        #computation of the salary input
        worked_days_line_ids = self.get_worked_day_lines(cr, uid, contract_ids, date_from, date_to, context=context)
        input_line_ids = self.get_inputs(cr, uid, contract_ids, date_from, date_to, context=context)
#         line_ids = self.get_line_idss(cr, uid,ids, contract_ids, context=context)
        
        res['value'].update({
#                     'line_ids':line_ids,
                    'worked_days_line_ids': worked_days_line_ids,
                    'input_line_ids': input_line_ids,
        })
        return res
     
#         for ot in self.pool.get('hr.overtime').browse(cr, uid, overtime_ids, context=context) :
#         
# class hr_payslip_line(osv.osv):
#     '''
#     Payslip Line
#     '''
# 
#     _name = 'hr.payslip.line'
#     _inherit = 'hr.salary.rule'
#     _description = 'Payslip Line'
#     _order = 'contract_id, sequence'
# 
#     def _calculate_total(self, cr, uid, ids, name, args, context):
#         if not ids: return {}
#         res = {}
#         for line in self.browse(cr, uid, ids, context=context):
#             res[line.id] = float(line.quantity) * line.amount * line.rate / 100
#         
#         print res
#         return res
# 
#     _columns = {
#         'slip_id':fields.many2one('hr.payslip', 'Pay Slip', required=True, ondelete='cascade'),
#         'salary_rule_id':fields.many2one('hr.salary.rule', 'Rule', required=True),
#         'employee_id':fields.many2one('hr.employee', 'Employee', required=True),
#         'contract_id':fields.many2one('hr.contract', 'Contract', required=True, select=True),
#         'rate': fields.float('Rate (%)', digits_compute=dp.get_precision('Payroll Rate')),
#         'amount': fields.float('Amount', digits_compute=dp.get_precision('Payroll')),
#         'quantity': fields.float('Quantity', digits_compute=dp.get_precision('Payroll')),
#         'total': fields.function(_calculate_total, method=True, type='float', string='Total nyaaaa', digits_compute=dp.get_precision('Payroll'),store=True ),
#     }
# 
#     _defaults = {
#         'quantity': 1.0,
#         'rate': 100.0,
#     }


# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
